package com.glp.work.flow.workflow.command;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.runtime.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.glp.work.flow.constant.APICode;
import com.glp.work.flow.constant.OrderStatus;
import com.glp.work.flow.exception.APIException;
import com.glp.work.flow.pojo.WfOrder;
import com.glp.work.flow.service.OrderInfoService;
import com.glp.work.flow.utils.DateUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 驳回上一级
 *
 * @author pengjia
 * @version 2020年6月5日 上午8:50:49
 */
@Component
@Slf4j
public class CommonJumpToUpperTaskCmd implements Command<Void> {

    private String procInstanceId;
    private String executionId;
    private String assigneeName;
    private static RuntimeService runtimeService;
    private static OrderInfoService orderInfoService;
    private static HistoryService historyService;
//    private static TaskService taskService;

    public CommonJumpToUpperTaskCmd() {
    }

    public CommonJumpToUpperTaskCmd(String procInstanceId, String executionId, String assigneeName) {
        this.procInstanceId = procInstanceId;
        this.executionId = executionId;
        this.assigneeName = assigneeName;
    }

    @Override
    public Void execute(CommandContext commandContext) {
    	List<HistoricActivityInstance> hisTasks = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInstanceId)
                .finished()
                .list().stream().filter(a -> a.getActivityType().equals("userTask")).collect(Collectors.toList());
        log.info("得到历史流程。executionId={}  hisTasks={}", executionId, hisTasks);
        if (CollectionUtils.isNotEmpty(hisTasks)) {
            List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(procInstanceId).list();
            log.info("过滤前执行IDs：{}", executions);
			if(CollectionUtils.isNotEmpty(executions)) {
		    	executions = executions.stream().filter(predicate->{
		    		if(predicate instanceof ExecutionEntityImpl) {
		    	        if (((ExecutionEntityImpl) predicate).isProcessInstanceType()) {
		    	            return false;
		    	        } else {
		    	            if (((ExecutionEntityImpl) predicate).isScope()) {
		    	                return false;
		    	            } else if (((ExecutionEntityImpl) predicate).isMultiInstanceRoot()) {
		    	                return false;
		    	            } else {
		    	            	 if(((ExecutionEntityImpl) predicate).isActive()){
		    	            		 return true;    	
				    	         }else {
				    	        	 return false;
				    	         }
		    	            }
		    	        }
		    		}
		    		return false;
		    	}).collect(Collectors.toList());
				List<String> executionIds = executions.stream().map(Execution::getId).collect(Collectors.toList());
				log.info("过滤后执行IDs：{}", executionIds);
	            //根据时间进行排序
	            Collections.sort(hisTasks, (a, b) -> a.getEndTime().compareTo(b.getEndTime()));
				if(hisTasks.stream().map(HistoricActivityInstance::getActivityId).collect(Collectors.toList()).contains(executions.get(0).getActivityId())) {
		            for (int i = 0; i < hisTasks.size(); ++i) {
		            	if (hisTasks.get(i).getActivityId().equals(executions.get(0).getActivityId())) {
		            		if(i==0) {
		            			updateOrderStatus(procInstanceId, assigneeName);        			
		            		}else {
			                    HistoricActivityInstance historicActivityInstance = hisTasks.get(i - 1);
			                    runtimeService.createChangeActivityStateBuilder().processInstanceId(this.procInstanceId)
			                            .moveExecutionsToSingleActivityId(executionIds, historicActivityInstance.getActivityId()).changeState();
			                    break;	
		            		}
		                }
		            }
				}else {
		            //取出最后一个历史节点
					log.info("取出最后一个历史节点");
		            HistoricActivityInstance max = hisTasks.get(hisTasks.size()-1);
                    runtimeService.createChangeActivityStateBuilder().processInstanceId(this.procInstanceId)
                    .moveExecutionsToSingleActivityId(executionIds, max.getActivityId()).changeState();					
				}
			}else {
				throw new APIException(APICode.DATA_ERROR, "驳回上一级失败，找不到正在执行的任务！"+ executions) ;
			}
        } else {
            updateOrderStatus(procInstanceId, assigneeName);

        }
        return null;
    }

    private void updateOrderStatus(String procInstanceId, String assigneeName) {
        log.info("已经是开始的第一岗任务！更新工单状态为：审批驳回。processId={}，executionId={}", procInstanceId);
        WfOrder record = new WfOrder();
        record.setProcessId(procInstanceId);
        record.setOrderStatus(OrderStatus.WAITNEWS.getCode());
        record.setUpdateTime(DateUtils.getCurrent());
        record.setUpdateUser(assigneeName);
        orderInfoService.updateWfOrder(procInstanceId, record);
    }

    @Autowired
    public void setRuntimeService(RuntimeService runtimeService) {
        CommonJumpToUpperTaskCmd.runtimeService = runtimeService;
    }

    @Autowired
    public void setOrderInfoService(OrderInfoService orderInfoService) {
        CommonJumpToUpperTaskCmd.orderInfoService = orderInfoService;
    }

    @Autowired
    public void setHistoryService(HistoryService historyService) {
        CommonJumpToUpperTaskCmd.historyService = historyService;
    }

//    @Autowired
//    public void setTaskService(TaskService taskService) {
//        CommonJumpToUpperTaskCmd.taskService = taskService;
//    }

}
